Loading...
 

Query and Index on Collections

Search in Collections

Collections can be searched for objects with certain properties using queries. ClassiX and ObjectStore support this with a simple but powerful query language. The commands for searching a collection are

  • Find
  • FindFirst
  • FindExist
FindAll is another "search" command, but it does not require a search expression, since it returns all objects of a REP collection. Find returns all objects with certain properties, FindFirst only the first one found.

Query with Find or FindFirst

The query language is described in : Query syntax

Queries are used to find objects with certain properties. This means that for each object in the collection, the system checks whether it meets a condition. The search expression is therefore always a condition, usually with my comparison (e.g. =, >, <, ~, @) or the query whether a slot exists (operator ?). The condition refers to a property of an object that is compared with another value. The property of the object is described by an access expression. An access expression is the path from the object via any number of other objects or collections to a specific other object or value (for example, a string). Members, slots, or function calls can lie along this path.

The target of the access expression is compared with something else. This other can be another object property (again described by an access expression), or a constant or a variable. In the search expression, a variable is identified by a placeholder (%...). Before execution, there must be a corresponding object on the stack for each placeholder. Constants can be numbers, character strings (in quotation marks) or values (number + unit, see CX_VALUE).

The search expressions in ClassiX differ from the ObjectStore notation: ObjectStore uses a very technical syntax, which is sometimes very difficult to understand (among other things ObjectStore itself does not know slots). Therefore a simplified form was implemented in ClassiX (both search expressions can be viewed via the Query Manager). When executing a query, the InstantView query expression is translated first. ObjectStore itself in turn translates the search expression into an internal representation. To accelerate this process, all queries are cached in ClassiX (only the queries, not the results). To find a query in the cache the InstantView query expression is used. Variables (placeholders) are therefore preferable to compound expressions with constants if different values are frequently queried.

For your information: Since ObjectStore does not know slots, they are mapped in ClassiX queries with the help of functions. Slots have an internal number, and in the translation of the query the slot name is translated by a function call. There are the global functions "f1()", "f2()", "f4()", "f8()", "f16()" and "f32()" for the different slot types (int, String, Object, ...), which get the slot number passed and return the slot.

Accelerating a query using an index

For a detailed description of how an index is built, see here.

A search in a sorted list is always faster than in an unsorted list. A collection itself can only keep its elements in a certain order. Indexes are created to enable you to search for objects quickly according to various criteria. An index is, so to speak, a virtual sorting of a collection.

In ClassiX, an index is managed (created, deleted, modified, ...) by the Index Manager and represented by an index descriptor. A query can use an index to get a result faster by sorting. An index describes an access path based on the elements of a collection. For a query to be accelerated by an index, the access path in the index must correspond to the access path in the query expression. The same applies as described above: The "simple" access expression in ClassiX is translated into the technical ObjectStore access expression.

For functions in ObjectStore indexes there is a special feature: No functions with parameters are allowed. Therefore, the functions used in queries cannot be used to reach the slots. Instead, special functions are used which have encoded the slot number and type of the slot using the function name: e.g. SlotFuncStr34(). In order to establish the assignment between slot and index function, the "classix.dic" file (or one of the files included from the ".ini" file) must contain the entry

Slot(<slotname>, <type>, ...)

...

Index(<slot name>, <slot number>)

must be entered. The slot name corresponds to the previously defined slot.

The access expression described in the index must always be the complete one from the objects in the collection to the target value. This can include any slots that have been defined with the .ini entry Index(...). Normally, the index sorts according to the value of the target objects (for example, the value of a CX_VALUE object or a string). In some cases the value or order is difficult to determine (e.g. how to sort a list of CX_PERSON objects). In these cases the identity of an object is often asked for and compared in the query with the identity operator '@'. In the access expression for the index, the entire access expression must be preceded by an '@' to distinguish that the address (identity) is to be used. Only then can the index be used in a query with an '@' operator.

The '@' at the beginning of the access expression in the index ensures that "SlotFuncPtr<Nr>()" is used as the last slot function in the ObjectStore index instead of "SlotFuncObj<Nr>()" and thus a pointer to the object instead of the object itself with its comparison operator is used for comparison.

Check whether an index is used

To speed up the application, it is recommended to create an index for many queries. It is helpful to see which queries are executed at all and which indexes are used.

To achieve this, monitoring can be switched on via the Query Manager with the function "StartMonitoringIndexUsage()". A file name is passed for this. In this file ObjectStore logs which queries are executed and which indexes are used. This allows you to check whether a newly created index actually accelerates the query for which it was intended.